package com.hw.protocol.tool.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.hw.protocol.tool.BootScript;
import com.hw.protocol.tool.config.DecodeContext;
import com.hw.protocol.tool.config.ProtocolType;
import com.hw.protocol.tool.controller.transform.HbTransform;
import com.hw.protocol.tool.controller.transform.HwTransform;
import com.hw.protocol.tool.controller.transform.JkTransform;
import com.hw.protocol.tool.controller.transform.TxTransform;
import com.hw.protocol.tool.decode.IDecode;
import com.hw.protocol.tool.model.History;
import com.hw.protocol.tool.model.Result;
import com.hw.protocol.tool.util.CrcUtil;
import com.hw.protocol.tool.util.ModelUtil;
import com.hw.protocol.tool.view.AboutView;
import com.hw.protocol.tool.view.HbKeyView;
import com.hw.protocol.tool.view.HistoryView;
import com.hw.protocol.tool.view.JkKeyView;
import de.felixroske.jfxsupport.FXMLController;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.stage.Modality;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

/**
 * @author : lihy
 * @date : 2024/3/11 15:56
 * description:
 */
@Slf4j
@FXMLController
public class IndexController {

    @FXML
    public MenuItem menuHistory;

    @FXML
    public MenuItem menuClose;

    @FXML
    public MenuItem menuKey;

    @FXML
    public Menu menuChoose;

    @FXML
    public MenuItem menuAbout;

    @FXML
    public Label labProtocolStatus;

    @FXML
    public Label labDecodeStatus;

    @FXML
    public Label labKey;

    @FXML
    public TextArea txtInput;

    @FXML
    public TextArea txtMeterData;

    @FXML
    public TextArea txtResult;

    @FXML
    public Button btnDecode;

    public void initialize() {
        for (String protocol : DecodeContext.PROTOCOL_LIST) {
            if (StrUtil.isNotEmpty(protocol)) {
                ProtocolType protocolType = ProtocolType.getByName(protocol);
                MenuItem item = new MenuItem(protocolType.getLabel());
                item.setOnAction(event -> {
                    DecodeContext.currentProtocol = protocol;
                    labProtocolStatus.setText(protocolType.getLabel());
                    txtMeterData.setText("");
                    txtResult.setText("");
                    txtInput.setText("");
                    DecodeContext.KEY_STATUS.setValue("未设置");
                    labDecodeStatus.setText("未解析");
                });
                menuChoose.getItems().add(item);
            }
        }

        labKey.textProperty().bind(DecodeContext.KEY_STATUS);
    }

    @FXML
    public void decode(ActionEvent actionEvent) {
        IDecode decode = null;
        try {
            decode = SpringUtil.getBean(DecodeContext.currentProtocol + "Decode");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            labDecodeStatus.setText("协议错误");
        }
        String in = txtInput.getText().replaceAll(" ", "");
        Result result = decode.decode(CrcUtil.convert16HexToByte(in));
        if (result.getCode() == 200) {
            try {
                String voName = result.getData().getClass().getName() + "Vo";
                Object vo = Class.forName(voName).newInstance();
                ModelUtil.entity2Vo(result.getData(), vo);
                String decodeStr = JSONUtil.toJsonStr(vo).replace(",", ",\n");
                txtResult.setText(decodeStr);
                labDecodeStatus.setText("解析成功");
                String dataStr = parseData(result.getData());
                History history = new History(new DateTime().toString(DatePattern.NORM_DATETIME_PATTERN),
                        txtInput.getText(),
                        decodeStr,
                        dataStr);
                DecodeContext.historyList.add(history);
                DecodeContext.historyObs.add(0, history);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            labDecodeStatus.setText(result.getMessage());
        }
    }


    @FXML
    public void close(ActionEvent actionEvent) {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("确认");
        alert.setHeaderText("退出系统");
        alert.setContentText("是否确认退出系统？");

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == ButtonType.OK) {
            System.exit(0);
        }
    }

    @FXML
    public void setKey(ActionEvent actionEvent) {


        if ("jk".equals(DecodeContext.currentProtocol)) {
            BootScript.showView(JkKeyView.class, Modality.NONE);
        } else if ("hb".equals(DecodeContext.currentProtocol)) {
            BootScript.showView(HbKeyView.class, Modality.NONE);
        } else {
            TextInputDialog dialog = new TextInputDialog("");
            dialog.setTitle("设置密钥");
            dialog.setHeaderText("设置密钥");
            dialog.setContentText("密钥:");
            dialog.setGraphic(new ImageView(BootScript.class.getResource("/images/key.png").toString()));
            dialog.getDialogPane().setPrefWidth(500);
            dialog.showAndWait().ifPresent(key -> {
                DecodeContext.KEY_STATUS.setValue(key);
                DecodeContext.key = key;
            });
        }

    }

    @FXML
    public void showHistory(ActionEvent actionEvent) {
        BootScript.showView(HistoryView.class, Modality.NONE);
    }

    /**
     * 解析数据
     *
     * @param data 解析后的协议
     */
    private String parseData(Object data) {
        ProtocolType protocolType = ProtocolType.getByName(DecodeContext.currentProtocol);
        String dataStr = "";
        try {
            switch (protocolType) {
                case HW:
                    dataStr = HwTransform.transform(data);
                    break;
                case HB:
                    dataStr = HbTransform.transform(data);
                    break;
                case TX:
                    dataStr = TxTransform.transform(data);
                    break;
                case JK:
                    dataStr = JkTransform.transform(data);
                default:
                    labDecodeStatus.setText("无匹配的协议");
            }
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
            dataStr = "无法解析数据";
        }
        txtMeterData.setText(dataStr);
        return dataStr;
    }

    @FXML
    public void showAbout(ActionEvent actionEvent) {
        BootScript.showView(AboutView.class, Modality.APPLICATION_MODAL);
    }
}
